package com.capgemini.fs.presentation.forum.web.action;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;

import com.capgemini.fs.app.ekms.model.Forum;
import com.capgemini.fs.app.ekms.persistence.util.QueryHelper;
import com.capgemini.fs.app.ekms.service.ForumService;
import com.capgemini.fs.app.ekms.service.util.data.ForumInfo;
import com.capgemini.fs.presentation.forum.web.form.VisitForumForm;

public class VisitForumAction extends DispatchAction {

	private ForumService visitForumService;
	private int pageSize = 10;

	public ForumService getVisitForumService() {
		return visitForumService;
	}

	public void setVisitForumService(ForumService visitForumService) {
		this.visitForumService = visitForumService;
	}

	// Sort ForumInfo list
	public List<ForumInfo> sortForumList(String sortType, String sortOrder,
			List<ForumInfo> list) {

		// Compare Forum By Forum Name
		Comparator<ForumInfo> compareByForumName = new Comparator<ForumInfo>() {
			public int compare(ForumInfo f1, ForumInfo f2) {
				return f1.getForumName().compareTo(f2.getForumName());
			}
		};

		// Compare Forum By Forum Status
		Comparator<ForumInfo> compareByForumStatus = new Comparator<ForumInfo>() {
			public int compare(ForumInfo f1, ForumInfo f2) {
				// return g1.getStatus().compareTo(g2.getStatus());
				if (!QueryHelper.isNullOrEmpty(f1.getStatus())
						&& !QueryHelper.isNullOrEmpty(f2.getStatus())) {
					if (f1.getStatus() < f2.getStatus()) {
						return -1;
					}
					if (f1.getStatus() > f2.getStatus()) {
						return 1;
					}
				}
				return 0;
			}
		};

		// Compare Forum By Forum Desc
		Comparator<ForumInfo> compareByForumDesc = new Comparator<ForumInfo>() {
			public int compare(ForumInfo f1, ForumInfo f2) {
				return f1.getDescription().compareTo(f2.getDescription());
			}
		};

		// compare Forum by Topic counts
		Comparator<ForumInfo> compareByTopicCounts = new Comparator<ForumInfo>() {
			public int compare(ForumInfo f1, ForumInfo f2) {
				return f1.getTopicCounts().compareTo(f2.getTopicCounts());
			}
		};

		// Compare Forum by posts counts

		Comparator<ForumInfo> compareByPostCounts = new Comparator<ForumInfo>() {
			public int compare(ForumInfo f1, ForumInfo f2) {
				return f1.getPostCounts().compareTo(f2.getPostCounts());
			}
		};
		
		// Compare Forum by last post time

		Comparator<ForumInfo> compareByLastPostTime = new Comparator<ForumInfo>() {
			public int compare(ForumInfo f1, ForumInfo f2) {
				if(f1.getLastTopic()==null&&f2.getLastTopic()!=null){
					return -1;
				}
				if(f1.getLastTopic()!=null&&f2.getLastTopic()==null){
					return 1;
				}if(f1.getLastTopic()==null&&f2.getLastTopic()==null){
					return 0;
				}else{
					return f1.getLastTopic().getCreateDate().compareTo(f2.getLastTopic().getCreateDate());
				}
				
			}
		};
		if (null == sortType) {
			Collections.sort(list, compareByForumName);
		}
		if ("name".equals(sortType)) {
			Collections.sort(list, compareByForumName);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		if ("status".equals(sortType)) {
			Collections.sort(list, compareByForumStatus);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		if ("topics".equals(sortType)) {
			Collections.sort(list,compareByTopicCounts);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		if ("posts".equals(sortType)) {
			Collections.sort(list, compareByPostCounts);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		if("lastPost".equals(sortType)){
			Collections.sort(list,compareByLastPostTime);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		
		}
		if ("desc".equals(sortType)) {
			Collections.sort(list, compareByForumDesc);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		return list;
	}

	// List all Forums when first enter the "modifyForum.jsp" page
	public ActionForward listForum(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		// get query criteria from ActionForm
		String forumNameQuery = ((VisitForumForm) form).getForumNameQuery();
		Integer forumActiveQuery = ((VisitForumForm) form)
				.getForumActiveQuery();
		// get sort parameters(sortType & sortOrder)
		String sortType = ((VisitForumForm) form).getSortType();
		String sortOrder = ((VisitForumForm) form).getSortOrder();

		// This list stored all the forums queried from database
		List<Forum> list;
		List<ForumInfo> forumInfoList = new ArrayList<ForumInfo>();
		// if forum status not decided, query forum depending on just forum
		// name.
		if (null == forumActiveQuery || 99 == forumActiveQuery) {
			list = visitForumService.queryForum(forumNameQuery, null);
			// Turn Forum to ForumInfo, encapsulate data
			GenerateForumInfoList(forumInfoList, list);
			forumActiveQuery = 99;
			// else query depending on both forum name and status
		} else {
			list = visitForumService.queryForum(forumNameQuery,
					forumActiveQuery);
			GenerateForumInfoList(forumInfoList, list);
		}

		sortForumList(sortType, sortOrder, forumInfoList);
		if (null == sortType) {
			sortType = "name";
			sortOrder = "asce";
		}
		// Total row number depends on the forum returned from server
		int totalRows = forumInfoList.size();
		// Initial current page at page 1
		int nowPage = 1;
		// Get page numbers
		int totalPage = getTotalPage(pageSize, totalRows);

		List<ForumInfo> data = new ArrayList<ForumInfo>();

		/**
		 * Add associated forums to current page
		 */
		if (totalRows >= nowPage * pageSize) {
			for (int i = nowPage - 1; i < nowPage * pageSize; i++) {
				data.add(forumInfoList.get(i));
			}
		} else {
			for (int i = nowPage - 1; i < totalRows; i++) {
				data.add(forumInfoList.get(i));
			}
		}
		// Set all the query conditions to request because we still need them on
		// page
		request.setAttribute("forumNameQuery", forumNameQuery);
		request.setAttribute("forumActiveQuery", forumActiveQuery);
		request.setAttribute("sortType", sortType);
		request.setAttribute("sortOrder", sortOrder);
		request.setAttribute("totalPage", nowPage + "/" + totalPage);
		request.setAttribute("nowPage", nowPage);
		// Return forums on current page back
		request.setAttribute("forumInfoList", data);
		request.setAttribute("totalPageNum", totalPage);
		request.setAttribute("statusMap", getStatusMap());
		return mapping.findForward("succ");
	}

	public HashMap<String, String> getStatusMap() {
		HashMap<String, String> map = new HashMap<String, String>();
		map.put("0", "Yes");
		map.put("1", "No");
		return map;
	}

	// Go to Next Page
	public ActionForward goToNextPage(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		String forumNameQuery = ((VisitForumForm) form).getForumNameQuery();
		Integer forumActiveQuery = ((VisitForumForm) form)
				.getForumActiveQuery();
		String sortType = ((VisitForumForm) form).getSortType();
		String sortOrder = ((VisitForumForm) form).getSortOrder();
		List<Forum> list;
		List<ForumInfo> forumInfoList = new ArrayList<ForumInfo>();
		if (forumActiveQuery == 99 || null == forumActiveQuery) {
			list = visitForumService.queryForum(forumNameQuery, null);
			GenerateForumInfoList(forumInfoList, list);

		} else {
			list = visitForumService.queryForum(forumNameQuery,
					forumActiveQuery);
			GenerateForumInfoList(forumInfoList, list);

		}

		sortForumList(sortType, sortOrder, forumInfoList);
		int totalRows = forumInfoList.size();

		VisitForumForm gmf = (VisitForumForm) form;
		int nowPage = gmf.getNowPage();
		int totalPage = getTotalPage(pageSize, totalRows);

		List<ForumInfo> data = new ArrayList<ForumInfo>();
		if (totalRows > (nowPage + 1) * pageSize) {
			for (int i = nowPage * pageSize; i < (nowPage + 1) * pageSize; i++) {
				data.add(forumInfoList.get(i));
			}
		} else {
			for (int i = nowPage * pageSize; i < totalRows; i++) {
				data.add(forumInfoList.get(i));
			}
		}
		nowPage = nowPage + 1;
		request.setAttribute("forumNameQuery", forumNameQuery);
		request.setAttribute("forumActiveQuery", forumActiveQuery);
		request.setAttribute("sortType", sortType);
		request.setAttribute("sortOrder", sortOrder);
		request.setAttribute("totalPage", nowPage + "/" + totalPage);
		request.setAttribute("nowPage", nowPage);
		request.setAttribute("forumInfoList", data);
		request.setAttribute("totalPageNum", totalPage);
		request.setAttribute("statusMap", getStatusMap());
		return mapping.findForward("succ");
	}

	// Go to Previous Page
	public ActionForward goToPreviousPage(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) {
		String forumNameQuery = ((VisitForumForm) form).getForumNameQuery();
		Integer forumActiveQuery = ((VisitForumForm) form)
				.getForumActiveQuery();
		String sortType = ((VisitForumForm) form).getSortType();
		String sortOrder = ((VisitForumForm) form).getSortOrder();
		List<Forum> list;
		List<ForumInfo> forumInfoList = new ArrayList<ForumInfo>();
		if (forumActiveQuery == 99 || null == forumActiveQuery) {
			list = visitForumService.queryForum(forumNameQuery, null);
			GenerateForumInfoList(forumInfoList, list);

		} else {
			list = visitForumService.queryForum(forumNameQuery,
					forumActiveQuery);
			GenerateForumInfoList(forumInfoList, list);

		}

		sortForumList(sortType, sortOrder, forumInfoList);
		int totalRows = forumInfoList.size();
		VisitForumForm gmf = (VisitForumForm) form;
		int nowPage = gmf.getNowPage();
		int totalPage = getTotalPage(pageSize, totalRows);

		List<ForumInfo> data = new ArrayList<ForumInfo>();
		if (nowPage - 2 >= 0) {
			for (int i = (nowPage - 2) * pageSize; i < (nowPage - 1) * pageSize; i++) {
				data.add(forumInfoList.get(i));
			}
		}

		nowPage = nowPage - 1;
		request.setAttribute("forumNameQuery", forumNameQuery);
		request.setAttribute("forumActiveQuery", forumActiveQuery);
		request.setAttribute("sortType", sortType);
		request.setAttribute("sortOrder", sortOrder);
		request.setAttribute("totalPage", nowPage + "/" + totalPage);
		request.setAttribute("nowPage", nowPage);
		request.setAttribute("forumInfoList", data);
		request.setAttribute("totalPageNum", totalPage);
		request.setAttribute("statusMap", getStatusMap());
		return mapping.findForward("succ");
	}

	// Go to Target Page
	public ActionForward goToTargetPage(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		String forumNameQuery = ((VisitForumForm) form).getForumNameQuery();
//		Integer forumActiveQuery = ((VisitForumForm) form)
//				.getForumActiveQuery();
		String sortType = ((VisitForumForm) form).getSortType();
		String sortOrder = ((VisitForumForm) form).getSortOrder();
		List<Forum> list;
		List<ForumInfo> forumInfoList = new ArrayList<ForumInfo>();
//		if (forumActiveQuery == 99 || null == forumActiveQuery) {
			list = visitForumService.queryForum(forumNameQuery, null);
			GenerateForumInfoList(forumInfoList, list);
		// } else {
		// list = visitForumService.queryForum(forumNameQuery,
		// forumActiveQuery);
		// GenerateForumInfoList(forumInfoList, list);
		// }
		sortForumList(sortType, sortOrder, forumInfoList);
		int totalRows = forumInfoList.size();
		VisitForumForm gmf = (VisitForumForm) form;
		// get target page number from ActionForm
		int nowPage = gmf.getTargetPage();
		int totalPage = getTotalPage(pageSize, totalRows);
		List<ForumInfo> data = new ArrayList<ForumInfo>();

		if (nowPage > 0 && nowPage <= totalPage) {
			// Call "getTargetPageForums(,,)" method to get forums displayed on
			// target page
			data = getTargetPageForums(forumInfoList, nowPage, totalRows);
		}

		request.setAttribute("forumNameQuery", forumNameQuery);
//		request.setAttribute("forumActiveQuery", forumActiveQuery);
		request.setAttribute("sortType", sortType);
		request.setAttribute("sortOrder", sortOrder);
		request.setAttribute("totalPage", nowPage + "/" + totalPage);
		request.setAttribute("nowPage", nowPage);
		request.setAttribute("forumInfoList", data);
		request.setAttribute("totalPageNum", totalPage);
		request.setAttribute("statusMap", getStatusMap());
		return mapping.findForward("succ");
	}

	// Get Forums on target page, This method is much useful
	public List<ForumInfo> getTargetPageForums(List<ForumInfo> list,
			int targetNum, int totalNum) {
		List<ForumInfo> data = new ArrayList<ForumInfo>();
		if (targetNum * pageSize <= totalNum) {
			for (int i = (targetNum - 1) * pageSize; i < (targetNum * pageSize); i++) {
				data.add(list.get(i));
			}
		} else {
			for (int i = (targetNum - 1) * pageSize; i < totalNum; i++) {
				data.add(list.get(i));
			}
		}
		return data;
	}

	public int getTotalPage(int pageSize, int totalRows) {
		int totalPage;
		if (totalRows % pageSize > 0) {
			totalPage = totalRows / pageSize + 1;
		} else {
			totalPage = totalRows / pageSize;
		}
		return totalPage;
	}

	// Query Forum
	public ActionForward queryForum(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		String forumNameQuery = ((VisitForumForm) form).getForumNameQuery();
		Integer forumActiveQuery = ((VisitForumForm) form)
				.getForumActiveQuery();
		if (forumActiveQuery == 99) {
			forumActiveQuery = null;
		}
		List<Forum> list = visitForumService.queryForum(forumNameQuery,
				forumActiveQuery);
		Collections.sort(list);
		return mapping.findForward("succ");
	}

	// Delete Forum
	// will not be used
	public ActionForward delete(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		try {
			@SuppressWarnings("unused")
			VisitForumForm VisitForumForm = (VisitForumForm) form;
			// ((Object)
			// modifyGroupService).deleteGroupbyId(modifyGroupForm.getGroupId());
			List<Forum> forumList = visitForumService.getAllForums();
			request.setAttribute("forumList", forumList);
			request.setAttribute("Success", "Deleted Successfully!");
			return mapping.findForward("succ");
		} catch (Exception e) {
			e.printStackTrace();
			request.setAttribute("Failed", "Deleted Failed!");
			return mapping.findForward("failed");
		}
	}

	// Turn Forum List into ForumInfo List in order to display on page
	public void GenerateForumInfoList(List<ForumInfo> forumInfoList,
			List<Forum> forumList) {
		for (Forum forum : forumList) {
			ForumInfo forumInfo = new ForumInfo();
			forumInfo.setId(forum.getId());
			forumInfo.setForumName(forum.getName());
			forumInfo.setNewTopicCountsToday(visitForumService
					.getNewTopicCountsToday(forum));
			forumInfo.setPostCounts(visitForumService.getPostCounts(forum));
			forumInfo.setDescription(forum.getDescription());
			forumInfo.setModerators(forum.getModerators());
			forumInfo.setTopicCounts(forum.getTopics().size());
			forumInfo.setStatus(forum.getStatus());
			forumInfo.setLastTopic(visitForumService.getLastTopic(forum));
			forumInfoList.add(forumInfo);
		}

	}

}
